#ifndef _HTTPFIXEDLENGTHSTREAM_HPP_
#define _HTTPFIXEDLENGTHSTREAM_HPP_

#include "jhdefs.hpp"
#include "types.hpp"
#include "net/HTTPSession.hpp"
#include "HTTPBasicStreamBuf.hpp"
#include "net/MemoryPool.hpp"

#include <istream>
#include <ostream>

NET_NAMESPACE_BEGIN

//
// CHTTPFixedLengthStreamBuf
//
class CHTTPFixedLengthStreamBuf : public HTTPBasicStreamBuf
{
public:
	typedef HTTPBasicStreamBuf::openmode openmode;

#if defined(JH_HAVE_INT64)
	typedef Int64 ContentLength;
#else
	typedef std::streamsize ContentLength;
#endif

	CHTTPFixedLengthStreamBuf(CHTTPSession& session, ContentLength length, openmode mode);
	~CHTTPFixedLengthStreamBuf();

protected:
	int readFromDevice(char* buffer, std::streamsize length);
	int writeToDevice(const char* buffer, std::streamsize length);

private:
	CHTTPSession& m_session;
	ContentLength m_length;
	ContentLength m_count;
};


//
// CHTTPFixedLengthIOS
//
class CHTTPFixedLengthIOS : public virtual std::ios
{
public:
	CHTTPFixedLengthIOS(CHTTPSession& session, CHTTPFixedLengthStreamBuf::ContentLength length, CHTTPFixedLengthStreamBuf::openmode mode);
	~CHTTPFixedLengthIOS();
	CHTTPFixedLengthStreamBuf* rdbuf();

protected:
	CHTTPFixedLengthStreamBuf m_buf;
};


//
// CHTTPFixedLengthInputStream
//
class CHTTPFixedLengthInputStream : public CHTTPFixedLengthIOS, public std::istream
{
public:
	CHTTPFixedLengthInputStream(CHTTPSession& session, CHTTPFixedLengthStreamBuf::ContentLength length);
	~CHTTPFixedLengthInputStream();

	void* operator new(std::size_t size);
	void operator delete(void* ptr);

private:
	static CMemoryPool m_pool;
};


//
// CHTTPFixedLengthOutputStream
//
class CHTTPFixedLengthOutputStream : public CHTTPFixedLengthIOS, public std::ostream
{
public:
	CHTTPFixedLengthOutputStream(CHTTPSession& session, CHTTPFixedLengthStreamBuf::ContentLength length);
	~CHTTPFixedLengthOutputStream();

	void* operator new(std::size_t size);
	void operator delete(void* ptr);

private:
	static CMemoryPool m_pool;
};

NET_NAMESPACE_END

#endif
